package com.xwli.springcloud.gof23.single;


/**
 * 懒汉式单例
 */
public class LazyMan {

    //构造器私有
    private LazyMan(){
        System.out.println(Thread.currentThread().getName()+"ok");
    }

    private volatile static LazyMan lazyMan;

    //双重检测锁模式的懒汉式单例 DCL懒汉式
    //1.但是这样依然还会有问题
    public static LazyMan getInstance(){
        if(lazyMan==null){
            synchronized (LazyMan.class){
                if(lazyMan==null){
                    lazyMan = new LazyMan(); //2.因为这个过程不是原子性操作
                    /**经历操作
                     * 2.1分配内存空间
                     * 2.2执行构造方法，初始化对象
                     * 2.3把这个对象指向2.1的内存空间
                     *
                     * 如果执行的是2.1 2 3是没有问题的
                     * 如果执行的不是2.1 2 3 是2.1 3 2 多线程情况会出问题
                     * 因为A线程2.1 3 2 是能够获取单例的，但是B线程会认为此时已经有单例了，就直
                     * return了，但事实上只是先占据了内存空间，还没有创建新对象，所以要加volatile关键字
                     * 防止指令重排
                     */
                }
            }
        }
        return lazyMan;
    }

    //假设是多线程并发
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                LazyMan.getInstance();
            }).start();
        }
    }
}
